package cn.colins.raft.rpc.session;


import cn.colins.raft.rpc.RpcClient;
import cn.colins.raft.config.ServerConfig;
import cn.colins.raft.rpc.session.defaults.DefaultRpcSession;
import cn.colins.raft.utils.ThreadPoolUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author colins
 * @Description 远程调用会话工厂
 **/
public class RpcSessionFactory {
    private static final Logger log = LoggerFactory.getLogger(RpcSessionFactory.class);

    /**
     * 通道缓存
     */
    private static Map<String, Channel> channelMap = new ConcurrentHashMap<>(16);
    /**
     * client缓存
     */
    private static Map<String, RpcClient> clientMap = new ConcurrentHashMap<>(16);


    public static <R, T> RpcSession<R, T> openSession(ServerConfig serverConfig, T request) {
        Channel channel = channelMap.get(serverConfig.toString());
        if (channel != null) {
            return new DefaultRpcSession<R, T>(channel, request);
        }

        RpcClient rpcClient = new RpcClient(serverConfig);
        if (rpcClient.getConnectStatus()) {
            ThreadPoolUtils.startNettyPool.execute(rpcClient);
            clientMap.put(serverConfig.toString(), rpcClient);
            channelMap.put(serverConfig.toString(), rpcClient.getChannelFuture());

            return new DefaultRpcSession<R, T>(rpcClient.getChannelFuture(), request);
        }
        return null;
    }


    public static void channelClear(ServerConfig serverConfig) {
        channelMap.remove(serverConfig.toString());
        RpcClient rpcClient = clientMap.get(serverConfig.toString());
        if (rpcClient != null) {
            rpcClient.destroy();
            clientMap.remove(serverConfig.toString());
        }
    }

    public static void channelClear() {
        for (Map.Entry<String, Channel> entry : channelMap.entrySet()) {
            // 释放连接
            channelMap.remove(entry.getKey());
            RpcClient rpcClient = clientMap.get(entry.getKey());
            if (rpcClient != null) {
                rpcClient.destroy();
                clientMap.remove(entry.getKey());
            }
        }
    }

}